home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / tc.os.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  28.6 KB  |  1,282 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/tc.os.c,v 3.27 1992/10/10 18:17:34 christos Exp $ */
  2. /*
  3.  * tc.os.c: OS Dependent builtin functions
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: tc.os.c,v 3.27 1992/10/10 18:17:34 christos Exp $")
  40.  
  41. #include "tw.h"
  42. #include "ed.h"
  43. #include "ed.defns.h"        /* for the function names */
  44. #include "sh.decls.h"
  45.  
  46. /***
  47.  *** MACH
  48.  ***/
  49.  
  50. #ifdef MACH
  51. /* dosetpath -- setpath built-in command
  52.  *
  53.  **********************************************************************
  54.  * HISTORY
  55.  * 08-May-88  Richard Draves (rpd) at Carnegie-Mellon University
  56.  *    Major changes to remove artificial limits on sizes and numbers
  57.  *    of paths.
  58.  *
  59.  **********************************************************************
  60.  */
  61.  
  62. #ifdef MACH
  63. static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
  64. static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
  65. static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
  66. # if EPATH
  67. static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
  68. # endif
  69. #endif /* MACH */
  70. static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH, 
  71.  
  72. #if EPATH
  73.     STREPATH,
  74. #endif
  75.      0};
  76. #define LOCALSYSPATH    "/usr/local"
  77.  
  78. /*ARGSUSED*/
  79. void
  80. dosetpath(arglist, c)
  81.     Char  **arglist;
  82.     struct command *c;
  83. {
  84.     extern char *getenv();
  85.     sigmask_t omask;
  86.     Char  **pathvars, **cmdargs;
  87.     char  **spaths, **cpaths, **cmds;
  88.     char   *tcp;
  89.     unsigned int npaths, ncmds;
  90.     int     i, sysflag;
  91.  
  92.     omask = sigsetmask(sigmask(SIGINT));
  93.  
  94.     /*
  95.      * setpath(3) uses stdio and we want 0, 1, 2 to work...
  96.      */
  97.     if (!didfds) {
  98.     (void) dcopy(SHIN, 0);
  99.     (void) dcopy(SHOUT, 1);
  100.     (void) dcopy(SHDIAG, 2);
  101.     didfds = 1;
  102.     }
  103.  
  104.     for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
  105.     npaths = i - 1;
  106.  
  107.     cmdargs = &arglist[i];
  108.     for (; arglist[i]; i++);
  109.     ncmds = i - npaths - 1;
  110.  
  111.     if (npaths) {
  112.     sysflag = 0;
  113.     pathvars = &arglist[1];
  114.     }
  115.     else {
  116.     sysflag = 1;
  117.     npaths = (sizeof syspaths / sizeof *syspaths) - 1;
  118.     pathvars = syspaths;
  119.     }
  120.  
  121.     /* note that npaths != 0 */
  122.  
  123.     spaths = (char **) xmalloc(npaths * sizeof *spaths);
  124.     setzero((char *) spaths, npaths * sizeof *spaths);
  125.     cpaths = (char **) xmalloc((npaths + 1) * sizeof *cpaths);
  126.     setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths);
  127.     cmds = (char **) xmalloc((ncmds + 1) * sizeof *cmds);
  128.     setzero((char *) cmds, (ncmds + 1) * sizeof *cmds);
  129.     for (i = 0; i < npaths; i++) {
  130.     char   *val = getenv(short2str(pathvars[i]));
  131.  
  132.     if (val == NULL)
  133.         val = "";
  134.  
  135.     spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val)
  136.                  + 2) * sizeof **spaths);
  137.     (void) strcpy(spaths[i], short2str(pathvars[i]));
  138.     (void) strcat(spaths[i], "=");
  139.     (void) strcat(spaths[i], val);
  140.     cpaths[i] = spaths[i];
  141.     }
  142.  
  143.     for (i = 0; i < ncmds; i++) {
  144.     Char   *val = globone(cmdargs[i], G_ERROR);
  145.  
  146.     if (val == NULL)
  147.         goto abortpath;
  148.     cmds[i] = xmalloc(Strlen(val) + 1);
  149.     (void) strcpy(cmds[i], short2str(val));
  150.     }
  151.  
  152.  
  153.     if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
  154. abortpath:
  155.     if (spaths) {
  156.         for (i = 0; i < npaths; i++)
  157.         if (spaths[i])
  158.             xfree((ptr_t) spaths[i]);
  159.         xfree((ptr_t) spaths);
  160.     }
  161.     if (cpaths)
  162.         xfree((ptr_t) cpaths);
  163.     if (cmds) {
  164.         for (i = 0; i < ncmds; i++)
  165.         if (cmds[i])
  166.             xfree((ptr_t) cmds[i]);
  167.         xfree((ptr_t) cmds);
  168.     }
  169.  
  170.     (void) sigsetmask(omask);
  171.     donefds();
  172.     return;
  173.     }
  174.  
  175.     for (i = 0; i < npaths; i++) {
  176.     Char    *val, *name;
  177.  
  178.     name = str2short(cpaths[i]);
  179.     for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
  180.     if (val && *val == '=') {
  181.         *val++ = '\0';
  182.  
  183.         tsetenv(name, val);
  184.         if (Strcmp(name, STRKPATH) == 0) {
  185.         importpath(val);
  186.         if (havhash)
  187.             dohash(NULL, NULL);
  188.         }
  189.         *--val = '=';
  190.     }
  191.     }
  192.     (void) sigsetmask(omask);
  193.     donefds();
  194. }
  195. #endif /* MACH */
  196.  
  197. /***
  198.  *** AIX
  199.  ***/
  200. #ifdef TCF
  201. /* ARGSUSED */
  202. void
  203. dogetxvers(v, c)
  204.     Char  **v;
  205.     struct command *c;
  206. {
  207.     char    xvers[MAXPATHLEN];
  208.  
  209.     if (getxvers(xvers, MAXPATHLEN) == -1)
  210.     stderror(ERR_SYSTEM, "getxvers", strerror(errno));
  211.     xprintf("%s\n", xvers);
  212.     flush();
  213. }
  214.  
  215. /*ARGSUSED*/
  216. void
  217. dosetxvers(v, c)
  218.     Char  **v;
  219.     struct command *c;
  220. {
  221.     char   *xvers;
  222.  
  223.     ++v;
  224.     if (!*v || *v[0] == '\0')
  225.     xvers = "";
  226.     else
  227.     xvers = short2str(*v);
  228.     if (setxvers(xvers) == -1)
  229.     stderror(ERR_SYSTEM, "setxvers", strerror(errno));
  230. }
  231.  
  232. #include <sf.h>
  233. #ifdef _AIXPS2
  234. # define XC_PDP11    0x01
  235. # define XC_23        0x02
  236. # define XC_Z8K        0x03
  237. # define XC_8086    0x04
  238. # define XC_68K        0x05
  239. # define XC_Z80        0x06
  240. # define XC_VAX        0x07
  241. # define XC_16032    0x08
  242. # define XC_286        0x09
  243. # define XC_386        0x0a
  244. # define XC_S370    0x0b
  245. #else
  246. # include <sys/x.out.h>
  247. #endif /* _AIXPS2 */
  248.  
  249. static struct xc_cpu_t {
  250.     short   xc_id;
  251.     char   *xc_name;
  252. }       xcpu[] =
  253. {
  254.     { XC_PDP11,    "pdp11"   },
  255.     { XC_23,    "i370"    },
  256.     { XC_Z8K,    "z8000"   },
  257.     { XC_8086,    "i86"      },
  258.     { XC_68K,    "mc68000" },
  259.     { XC_Z80,    "x80"      },
  260.     { XC_VAX,    "vax"      },
  261.     { XC_16032,    "ns16032" },
  262.     { XC_286,    "i286"      },
  263.     { XC_386,    "i386"      },
  264.     { XC_S370,    "xa370"      },
  265.     { 0,    NULL      }
  266. };
  267.  
  268. /*
  269.  * our local hack table, stolen from x.out.h
  270.  */
  271. static char *
  272. getxcode(xcid)
  273.     short   xcid;
  274. {
  275.     int     i;
  276.  
  277.     for (i = 0; xcpu[i].xc_name != NULL; i++)
  278.     if (xcpu[i].xc_id == xcid)
  279.         return (xcpu[i].xc_name);
  280.     return (NULL);
  281. }
  282.  
  283. static short
  284. getxid(xcname)
  285.     char   *xcname;
  286. {
  287.     int     i;
  288.  
  289.     for (i = 0; xcpu[i].xc_name != NULL; i++)
  290.     if (strcmp(xcpu[i].xc_name, xcname) == 0)
  291.         return (xcpu[i].xc_id);
  292.     return ((short) -1);
  293. }
  294.  
  295.  
  296. /*ARGSUSED*/
  297. void
  298. dogetspath(v, c)
  299.     Char  **v;
  300.     struct command *c;
  301. {
  302.     int     i, j;
  303.     sitepath_t p[MAXSITE];
  304.     struct sf *st;
  305.     static char *local = "LOCAL ";
  306.  
  307.     if ((j = getspath(p, MAXSITE)) == -1)
  308.     stderror(ERR_SYSTEM, "getspath", strerror(errno));
  309.     for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
  310.     if (p[i] & SPATH_CPU) {
  311.         if ((p[i] & SPATH_MASK) == NULLSITE)
  312.         xprintf(local);
  313.         else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
  314.         xprintf("%s ", st->sf_ctype);
  315.         else {
  316.         char   *xc = getxcode(p[i] & SPATH_MASK);
  317.  
  318.         if (xc != NULL)
  319.             xprintf("%s ", xc);
  320.         else
  321.             xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
  322.         /* 
  323.          * BUG in the aix code... needs that cause if
  324.          * sfxcode fails once it fails for ever 
  325.          */
  326.         endsf();    
  327.         }
  328.     }
  329.     else {
  330.         if (p[i] == NULLSITE)
  331.         xprintf(local);
  332.         else if ((st = sfnum(p[i])) != NULL)
  333.         xprintf("%s ", st->sf_sname);
  334.         else
  335.         xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
  336.     }
  337.     }
  338.     xputchar('\n');
  339.     flush();
  340. }
  341.  
  342. /*ARGSUSED*/
  343. void
  344. dosetspath(v, c)
  345.     Char  **v;
  346.     struct command *c;
  347. {
  348.     int     i;
  349.     short   j;
  350.     char   *s;
  351.     sitepath_t p[MAXSITE];
  352.     struct sf *st;
  353.  
  354.     /*
  355.      * sfname() on AIX G9.9 at least, mallocs too pointers p, q
  356.      * then does the equivalent of while (*p++ == *q++) continue;
  357.      * and then tries to free(p,q) them! Congrats to the wizard who
  358.      * wrote that one. I bet he tested it really well too.
  359.      * Sooo, we set dont_free :-)
  360.      */
  361.     dont_free = 1;
  362.     for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
  363.     s = short2str(*v);
  364.     if (Isdigit(*s))
  365.         p[i] = atoi(s);
  366.     else if (strcmp(s, "LOCAL") == 0)
  367.         p[i] = NULLSITE;
  368.     else if ((st = sfctype(s)) != NULL)
  369.         p[i] = SPATH_CPU | st->sf_ccode;
  370.     else if ((j = getxid(s)) != -1)
  371.         p[i] = SPATH_CPU | j;
  372.     else if ((st = sfname(s)) != NULL)
  373.         p[i] = st->sf_id;
  374.     else {
  375.         setname(s);
  376.         stderror(ERR_NAME | ERR_STRING, "Bad cpu/site name");
  377.     }
  378.     if (i == MAXSITE - 1)
  379.         stderror(ERR_NAME | ERR_STRING, "Site path too long");
  380.     }
  381.     if (setspath(p, i) == -1)
  382.     stderror(ERR_SYSTEM, "setspath", strerror(errno));
  383.     dont_free = 0;
  384. }
  385.  
  386. /* sitename():
  387.  *    Return the site name where the process is running
  388.  */
  389. char   *
  390. sitename(pid)
  391.     pid_t   pid;
  392. {
  393.     siteno_t ss;
  394.     struct sf *st;
  395.  
  396.     if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
  397.     return ("unknown");
  398.     else
  399.     return (st->sf_sname);
  400. }
  401.  
  402. static int
  403. migratepid(pid, new_site)
  404.     pid_t   pid;
  405.     siteno_t new_site;
  406. {
  407.     struct sf *st;
  408.     int     need_local;
  409.  
  410.     need_local = (pid == 0) || (pid == getpid());
  411.  
  412.     if (kill3((pid_t) pid, SIGMIGRATE, new_site) < 0) {
  413.     xprintf("%d: %s\n", pid, strerror(errno));
  414.     return (-1);
  415.     }
  416.  
  417.     if (need_local) {
  418.     if ((new_site = site(0)) == -1) {
  419.         xprintf("site: %s\n", strerror(errno));
  420.         return (-1);
  421.     }
  422.     if ((st = sfnum(new_site)) == NULL) {
  423.         xprintf("%d: Site not found\n", new_site);
  424.         return (-1);
  425.     }
  426.     if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
  427.         xprintf("setlocal: %s: %s\n", st->sf_local, strerror(errno));
  428.         return (-1);
  429.     }
  430.     }
  431.     return (0);
  432. }
  433.  
  434. /*ARGSUSED*/
  435. void
  436. domigrate(v, c)
  437.     Char  **v;
  438.     struct command *c;
  439. {
  440.     struct sf *st;
  441.     char   *s;
  442.     Char   *cp;
  443.     struct process *pp;
  444.     int     pid, err1 = 0;
  445.     siteno_t new_site = 0;
  446.     sigmask_t omask;
  447.  
  448. #ifdef BSDSIGS
  449.     omask = sigmask(SIGCHLD);
  450.     if (setintr)
  451.     omask |= sigmask(SIGINT);
  452.     omask = sigblock(omask) & ~omask;
  453. #else
  454.     if (setintr)
  455.     (void) sighold(SIGINT);
  456.     (void) sighold(SIGCHLD);
  457. #endif /* BSDSIGS */
  458.  
  459.     ++v;
  460.     if (*v[0] == '-') {
  461.     /*
  462.      * Do the -site.
  463.      */
  464.     s = short2str(&v[0][1]);
  465.     /*
  466.      * see comment in setspath()
  467.      */
  468.     dont_free = 1;
  469.     if ((st = sfname(s)) == NULL) {
  470.         setname(s);
  471.         stderror(ERR_NAME | ERR_STRING, "Site not found");
  472.     }
  473.     dont_free = 0;
  474.     new_site = st->sf_id;
  475.     ++v;
  476.     }
  477.  
  478.     if (!*v || *v[0] == '\0') {
  479.     if (migratepid(0, new_site) == -1)
  480.         err1++;
  481.     }
  482.     else {
  483.     gflag = 0, tglob(v);
  484.     if (gflag) {
  485.         v = globall(v);
  486.         if (v == 0)
  487.         stderror(ERR_NAME | ERR_NOMATCH);
  488.     }
  489.     else {
  490.         v = gargv = saveblk(v);
  491.         trim(v);
  492.     }
  493.  
  494.     while (v && (cp = *v)) {
  495.         if (*cp == '%') {
  496.         pp = pfind(cp);
  497.         if (kill3((pid_t) - pp->p_jobid, SIGMIGRATE, new_site) < 0) {
  498.             xprintf("%S: %s\n", cp, strerror(errno));
  499.             err1++;
  500.         }
  501.         }
  502.         else if (!(Isdigit(*cp) || *cp == '-'))
  503.         stderror(ERR_NAME | ERR_JOBARGS);
  504.         else {
  505.         pid = atoi(short2str(cp));
  506.         if (migratepid(pid, new_site) == -1)
  507.             err1++;
  508.         }
  509.         v++;
  510.     }
  511.     if (gargv)
  512.         blkfree(gargv), gargv = 0;
  513.     }
  514.  
  515. done:
  516. #ifdef BSDSIGS
  517.     (void) sigsetmask(omask);
  518. #else
  519.     (void) sigrelse(SIGCHLD);
  520.     if (setintr)
  521.     (void) sigrelse(SIGINT);
  522. #endif /* BSDSIGS */
  523.     if (err1)
  524.     stderror(ERR_SILENT);
  525. }
  526.  
  527. #endif /* TCF */
  528.  
  529. /***
  530.  *** CONVEX Warps.
  531.  ***/
  532.  
  533. #ifdef WARP
  534. /*
  535.  * handle the funky warping of symlinks
  536.  */
  537. #include <warpdb.h>
  538. #include <sys/warp.h>
  539.  
  540. static jmp_buf sigsys_buf;
  541.  
  542. static  sigret_t
  543. catch_sigsys()
  544. {
  545.     longjmp(sigsys_buf, 1);
  546. }
  547.  
  548.  
  549. /*ARGSUSED*/
  550. void
  551. dowarp(v, c)
  552.     Char  **v;
  553.     struct command *c;
  554. {
  555.     int     warp, oldwarp;
  556.     struct warpent *we;
  557.     void    (*old_sigsys_handler) () = 0;
  558.     char   *newwarp;
  559.  
  560.     if (setjmp(sigsys_buf)) {
  561.     signal(SIGSYS, old_sigsys_handler);
  562.     stderror(ERR_NAME | ERR_STRING, 
  563.          "You're trapped in a universe you never made");
  564.     return;
  565.     }
  566.     old_sigsys_handler = signal(SIGSYS, catch_sigsys);
  567.  
  568.     warp = getwarp();
  569.  
  570.     v++;
  571.     if (*v == 0) {        /* display warp value */
  572.     if (warp < 0)
  573.         stderror(ERR_NAME | ERR_STRING, "Getwarp failed");
  574.     we = getwarpbyvalue(warp);
  575.     if (we)
  576.         printf("%s\n", we->w_name);
  577.     else
  578.         printf("%d\n", warp);
  579.     }
  580.     else {            /* set warp value */
  581.     oldwarp = warp;
  582.     newwarp = short2str(*v);
  583.     if (Isdigit(*v[0]))
  584.         warp = atoi(newwarp);
  585.     else {
  586.         we = getwarpbyname(newwarp);
  587.         if (we)
  588.         warp = we->w_value;
  589.         else
  590.         warp = -1;
  591.     }
  592.     if ((warp < 0) || (warp >= WARP_MAXLINK))
  593.         stderror(ERR_NAME | ERR_STRING, "Invalid warp");
  594.     if ((setwarp(warp) < 0) || (getwarp() != warp)) {
  595.         (void) setwarp(oldwarp);
  596.         stderror(ERR_NAME | ERR_STRING, "Setwarp failed");
  597.     }
  598.     }
  599.     signal(SIGSYS, old_sigsys_handler);
  600.     return;
  601. }
  602. #endif /* WARP */
  603.  
  604. /***
  605.  *** Masscomp
  606.  ***/
  607. /* Added, DAS DEC-90. */
  608. #ifdef masscomp
  609. /*ARGSUSED*/
  610. void
  611. douniverse(v, c)
  612.     register Char **v;
  613.     struct command *c;
  614. {
  615.     register Char *cp = v[1];
  616.     char    ubuf[100];
  617.  
  618.     if (cp == 0) {
  619.     (void) getuniverse(ubuf);
  620.     xprintf("%s\n", ubuf);
  621.     }
  622.     else if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
  623.     stderror(ERR_NAME | ERR_STRING, "Illegal universe");
  624. }
  625. #endif /* masscomp */
  626.  
  627.  
  628. #ifdef _SEQUENT_
  629. /*
  630.  * Compute the difference in process stats.
  631.  */
  632. void
  633. pr_stat_sub(p2, p1, pr)
  634.     struct process_stats *p2, *p1, *pr;
  635. {
  636.     pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
  637.     pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
  638.     if (pr->ps_utime.tv_usec < 0) {
  639.     pr->ps_utime.tv_sec -= 1;
  640.     pr->ps_utime.tv_usec += 1000000;
  641.     }
  642.     pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
  643.     pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
  644.     if (pr->ps_stime.tv_usec < 0) {
  645.     pr->ps_stime.tv_sec -= 1;
  646.     pr->ps_stime.tv_usec += 1000000;
  647.     }
  648.  
  649.     pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
  650.     pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
  651.     pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
  652.     pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
  653.     pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
  654.     pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
  655.     pr->ps_swap = p2->ps_swap - p1->ps_swap;
  656.     pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
  657.     pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
  658.     pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
  659.     pr->ps_signal = p2->ps_signal - p1->ps_signal;
  660.     pr->ps_lread = p2->ps_lread - p1->ps_lread;
  661.     pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
  662.     pr->ps_bread = p2->ps_bread - p1->ps_bread;
  663.     pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
  664.     pr->ps_phread = p2->ps_phread - p1->ps_phread;
  665.     pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
  666. }
  667.  
  668. #endif /* _SEQUENT_ */
  669.  
  670.  
  671. #ifdef NEEDmemmove
  672. /* memmove():
  673.  *     This is the ANSI form of bcopy() with the arguments backwards...
  674.  *    Unlike memcpy(), it handles overlaps between source and 
  675.  *    destination memory
  676.  */
  677. void*
  678. xmemmove(vdst, vsrc, len)
  679.     ptr_t vdst;
  680.     const ptr_t vsrc;
  681.     size_t len;
  682. {
  683.     const char *src = (char *) vsrc;
  684.     char *dst = (char *) vdst;
  685.  
  686.     if (src == dst)
  687.     return vdst;
  688.  
  689.     if (src > dst) {
  690.     while (len--) 
  691.         *dst++ = *src++;
  692.     }
  693.     else {
  694.     src += len;
  695.     dst += len;
  696.     while (len--) 
  697.         *--dst = *--src;
  698.     }
  699.     return vdst;
  700. }
  701. #endif /* NEEDmemmove */
  702.  
  703.  
  704. #ifdef tcgetpgrp
  705. int
  706. xtcgetpgrp(fd)
  707.     int     fd;
  708. {
  709.     int     pgrp;
  710.  
  711.     /* ioctl will handle setting errno correctly. */
  712.     if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
  713.     return (-1);
  714.     return (pgrp);
  715. }
  716.  
  717. /*
  718.  * XXX: tcsetpgrp is not a macro any more cause on some systems,
  719.  * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
  720.  * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
  721.  * this out.
  722.  */
  723. int
  724. xtcsetpgrp(fd, pgrp)
  725.     int fd, pgrp;
  726. {
  727.     return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
  728. }
  729.  
  730. #endif    /* tcgetpgrp */
  731.  
  732.  
  733. #ifdef YPBUGS
  734. void
  735. fix_yp_bugs()
  736. {
  737.     char   *mydomain;
  738.  
  739.     /*
  740.      * PWP: The previous version assumed that yp domain was the same as the
  741.      * internet name domain.  This isn't allways true. (Thanks to Mat Landau
  742.      * <mlandau@bbn.com> for the original version of this.)
  743.      */
  744.     if (yp_get_default_domain(&mydomain) == 0) {    /* if we got a name */
  745.     extern void yp_unbind();
  746.  
  747.     yp_unbind(mydomain);
  748.     }
  749. }
  750.  
  751. #endif /* YPBUGS */
  752.  
  753. #ifdef STRCOLLBUG
  754. void
  755. fix_strcoll_bug()
  756. {
  757. #if defined(NLS) && !defined(NOSTRCOLL)
  758.     /*
  759.      * SunOS4 checks the file descriptor from openlocale() for <= 0
  760.      * instead of == -1. Someone should tell sun that file descriptor 0
  761.      * is valid! Our portable hack: open one so we call it with 0 used...
  762.      * We have to call this routine every time the locale changes...
  763.      *
  764.      * Of course it also tries to free the constant locale "C" it initially
  765.      * had allocated, with the sequence 
  766.      * > setenv LANG "fr"
  767.      * > ls^D
  768.      * > unsetenv LANG
  769.      * But we are smarter than that and just print a warning message.
  770.      */
  771.     int fd = -1;
  772.     static char *root = "/";
  773.  
  774.     if (!didfds)
  775.     fd = open(root, O_RDONLY);
  776.  
  777.     (void) strcoll(root, root);
  778.  
  779.     if (fd != -1)
  780.     (void) close(fd);
  781. #endif
  782. }
  783. #endif /* STRCOLLBUG */
  784.  
  785.  
  786. #ifdef OREO
  787. #include <compat.h>
  788. #endif /* OREO */
  789.  
  790. void
  791. osinit()
  792. {
  793. #ifdef OREO
  794.     set42sig();
  795.     setcompat(getcompat() & ~COMPAT_EXEC);
  796.     sigignore(SIGIO);        /* ignore SIGIO */
  797. #endif /* OREO */
  798.  
  799. #ifdef aiws
  800.     {
  801.     struct sigstack inst;
  802.     inst.ss_sp = xmalloc(4192) + 4192;
  803.     inst.ss_onstack = 0;
  804.     sigstack(&inst, NULL);
  805.     }
  806. #endif /* aiws */
  807.  
  808. #ifdef apollo
  809.     (void) isapad();
  810. #endif
  811. }
  812.  
  813. #ifdef strerror
  814. char *
  815. xstrerror(i)
  816.     int i;
  817. {
  818.     static char errbuf[40]; /* 64 bit num */
  819.  
  820.     if (i >= 0 && i < sys_nerr) 
  821.     return sys_errlist[i];
  822.     else {
  823.     xsprintf(errbuf, "Unknown Error: %d", i);
  824.     return errbuf;
  825.     }
  826. }
  827. #endif /* strerror */
  828.     
  829. #ifdef gethostname
  830. # if !defined(_MINIX) && !defined(__EMX__)
  831. #  include <sys/utsname.h>
  832. # endif /* !_MINIX && !__EMX__ */
  833.  
  834. int
  835. xgethostname(name, namlen)
  836.     char   *name;
  837.     int     namlen;
  838. {
  839. # if !defined(_MINIX) && !defined(__EMX__)
  840.     int     i, retval;
  841.     struct utsname uts;
  842.  
  843.     retval = uname(&uts);
  844.  
  845. #  ifdef DEBUG
  846.     xprintf("sysname:  %s\n", uts.sysname);
  847.     xprintf("nodename: %s\n", uts.nodename);
  848.     xprintf("release:  %s\n", uts.release);
  849.     xprintf("version:  %s\n", uts.version);
  850.     xprintf("machine:  %s\n", uts.machine);
  851. #  endif /* DEBUG */
  852.     i = strlen(uts.nodename) + 1;
  853.     (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
  854.  
  855.     return retval;
  856. # else /* !_MINIX && !__EMX__ */
  857.     if (namlen > 0) {
  858. #  ifdef __EMX__
  859.     (void) strncpy(name, "OS/2", namlen);
  860. #  else /* _MINIX */
  861.     (void) strncpy(name, "minix", namlen);
  862. #  endif /* __EMX__ */
  863.     name[namlen-1] = '\0';
  864.     }
  865.     return(0);
  866. #endif /* _MINIX && !__EMX__ */
  867. } /* end xgethostname */
  868. #endif /* gethostname */
  869.  
  870. #ifdef nice
  871. # if defined(_MINIX) && defined(NICE)
  872. #  undef _POSIX_SOURCE    /* redefined in <lib.h> */
  873. #  undef _MINIX        /* redefined in <lib.h> */
  874. #  undef HZ        /* redefined in <minix/const.h> */
  875. #  include <lib.h>
  876. # endif /* _MINIX && NICE */
  877. int 
  878. xnice(incr)
  879.     int incr;
  880. {
  881. #if defined(_MINIX) && defined(NICE)
  882.     return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
  883. #else
  884.     return /* incr ? 0 : */ 0;
  885. #endif /* _MINIX && NICE */
  886. } /* end xnice */
  887. #endif /* nice */
  888.  
  889. #ifdef getwd
  890. static char *strrcpy __P((char *, char *));
  891.  
  892. /* xgetwd():
  893.  *    Return the pathname of the current directory, or return
  894.  *    an error message in pathname.
  895.  */
  896.  
  897. # ifdef hp9000s500
  898. /*
  899.  *  From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
  900.  *  I also ported the tcsh to the HP9000 Series 500. This computer
  901.  *  is a little bit different than the other HP 9000 computer. It has
  902.  *  a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
  903.  *  HP-UX which is emulated in top of a HP operating system. So, the last
  904.  *  supported version of HP-UX is 5.2 on the HP9000s500. This has two
  905.  *  consequences: it supports no job control and it has a filesystem
  906.  *  without "." and ".." !!!
  907.  */
  908. static int pathsize;            /* pathname length */
  909.  
  910. char *
  911. xgetwd(pathname)
  912.     char *pathname;
  913. {
  914.     char pathbuf[MAXNAMLEN];    /* temporary pathname buffer */
  915.     char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
  916.     char *prepend();        /* prepend dirname to pathname */
  917.     dev_t rdev;            /* root device number */
  918.     DIR *dirp;            /* directory stream */
  919.     ino_t rino;            /* root inode number */
  920.     off_t rsize;            /* root size */
  921.     struct direct *dir;        /* directory entry struct */
  922.     struct stat d ,dd;        /* file status struct */
  923.  
  924.     pathsize = 0;
  925.     *pnptr = '\0';
  926.     stat("/.", &d);
  927.     rdev = d.st_dev;
  928.     rino = d.st_ino;
  929.     rsize = d.st_size;
  930.     for (;;) {
  931.         stat(".", &d);
  932.         if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
  933.             break;        /* reached root directory */
  934.         if ((dirp = opendir("..")) == NULL) {
  935.                 (void) xsprintf(pathname,
  936.                         "getwd: Cannot open \"..\" (%s)", strerror(errno));
  937.             goto fail;
  938.         }
  939.         if (chdir("..") < 0) {
  940.                 (void) xsprintf(pathname,
  941.                         "getwd: Cannot chdir to \"..\" (%s)", strerror(errno));
  942.             goto fail;
  943.         }
  944.         do {
  945.             if((dir = readdir(dirp)) == NULL) {
  946.                 closedir(dirp);
  947.                     (void) xsprintf(pathname,
  948.                             "getwd: Read error in \"..\" (%s)",
  949.                 strerror(errno));
  950.                 goto fail;
  951.             }
  952.             stat(dir->d_name, &dd);
  953.         } while (dd.st_ino  != d.st_ino  ||
  954.              dd.st_dev  != d.st_dev  ||
  955.              dd.st_size != d.st_size
  956.             );
  957.         closedir(dirp);
  958.         pnptr = prepend("/", prepend(dir->d_name, pnptr));
  959.     }
  960.  
  961.     if (*pnptr == '\0')        /* current dir == root dir */
  962.         strcpy(pathname, "/");
  963.     else {
  964.         strcpy(pathname, pnptr);
  965.         if (chdir(pnptr) < 0) {
  966.                 (void) xsprintf(pathname,
  967.                         "getwd: Cannot change back to \".\" (%s)",
  968.             strerror(errno));
  969.             return (NULL);
  970.         }
  971.     }
  972.     return (pathname);
  973.  
  974. fail:
  975.     chdir(prepend(".", pnptr));
  976.     return (NULL);
  977. }
  978.  
  979. /* prepend():
  980.  *     tacks a directory name onto the front of a pathname.
  981.  */
  982. static char *
  983. prepend(dirname, pathname)
  984.     register char *dirname;
  985.     register char *pathname;
  986. {
  987.     register int i;            /* directory name size counter */
  988.  
  989.     for (i = 0; *dirname != '\0'; i++, dirname++)
  990.         continue;
  991.     if ((pathsize += i) < MAXNAMLEN)
  992.         while (i-- > 0)
  993.             *--pathname = *--dirname;
  994.     return (pathname);
  995. }
  996.  
  997. # else /* ! hp9000s500 */
  998.  
  999. #if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX)
  1000. # define d_fileno d_ino
  1001. #endif
  1002.  
  1003. char   *
  1004. xgetwd(pathname)
  1005.     char   *pathname;
  1006. {
  1007.     DIR    *dp;
  1008.     struct dirent *d;
  1009.  
  1010.     struct stat st_root, st_cur, st_next, st_dotdot;
  1011.     char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
  1012.     char   *pathptr, *nextpathptr, *cur_name_add;
  1013.  
  1014.     /* find the inode of root */
  1015.     if (stat("/", &st_root) == -1) {
  1016.     (void) xsprintf(pathname,
  1017.             "getwd: Cannot stat \"/\" (%s)", strerror(errno));
  1018.     return (NULL);
  1019.     }
  1020.     pathbuf[MAXPATHLEN - 1] = '\0';
  1021.     pathptr = &pathbuf[MAXPATHLEN - 1];
  1022.     nextpathbuf[MAXPATHLEN - 1] = '\0';
  1023.     cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
  1024.  
  1025.     /* find the inode of the current directory */
  1026.     if (lstat(".", &st_cur) == -1) {
  1027.     (void) xsprintf(pathname,
  1028.             "getwd: Cannot stat \".\" (%s)", strerror(errno));
  1029.     return (NULL);
  1030.     }
  1031.     nextpathptr = strrcpy(nextpathptr, "../");
  1032.  
  1033.     /* Descend to root */
  1034.     for (;;) {
  1035.  
  1036.     /* look if we found root yet */
  1037.     if (st_cur.st_ino == st_root.st_ino &&
  1038.         DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
  1039.         (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
  1040.         return (pathname);
  1041.     }
  1042.  
  1043.     /* open the parent directory */
  1044.     if (stat(nextpathptr, &st_dotdot) == -1) {
  1045.         (void) xsprintf(pathname,
  1046.                 "getwd: Cannot stat directory \"%s\" (%s)",
  1047.                 nextpathptr, strerror(errno));
  1048.         return (NULL);
  1049.     }
  1050.     if ((dp = opendir(nextpathptr)) == NULL) {
  1051.         (void) xsprintf(pathname,
  1052.                 "getwd: Cannot open directory \"%s\" (%s)",
  1053.                 nextpathptr, strerror(errno));
  1054.         return (NULL);
  1055.     }
  1056.  
  1057.     /* look in the parent for the entry with the same inode */
  1058.     if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
  1059.         /* Parent has same device. No need to stat every member */
  1060.         for (d = readdir(dp); d != NULL; d = readdir(dp)) 
  1061.         if (d->d_fileno == st_cur.st_ino)
  1062.             break;
  1063.     }
  1064.     else {
  1065.         /* 
  1066.          * Parent has a different device. This is a mount point so we 
  1067.          * need to stat every member 
  1068.          */
  1069.         for (d = readdir(dp); d != NULL; d = readdir(dp)) {
  1070.         if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
  1071.             continue;
  1072.         (void) strcpy(cur_name_add, d->d_name);
  1073.         if (lstat(nextpathptr, &st_next) == -1) {
  1074.             (void) xsprintf(pathname, "getwd: Cannot stat \"%s\" (%s)",
  1075.                     d->d_name, strerror(errno));
  1076.             (void) closedir(dp);
  1077.             return (NULL);
  1078.         }
  1079.         /* check if we found it yet */
  1080.         if (st_next.st_ino == st_cur.st_ino &&
  1081.             DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) 
  1082.             break;
  1083.         }
  1084.     }
  1085.     if (d == NULL) {
  1086.         (void) xsprintf(pathname, "getwd: Cannot find \".\" in \"..\"");
  1087.         (void) closedir(dp);
  1088.         return (NULL);
  1089.     }
  1090.     st_cur = st_dotdot;
  1091.     pathptr = strrcpy(pathptr, d->d_name);
  1092.     pathptr = strrcpy(pathptr, "/");
  1093.     nextpathptr = strrcpy(nextpathptr, "../");
  1094.     (void) closedir(dp);
  1095.     *cur_name_add = '\0';
  1096.     }
  1097. } /* end getwd */
  1098.  
  1099. /* strrcpy():
  1100.  *    Like strcpy, going backwards and returning the new pointer
  1101.  */
  1102. static char *
  1103. strrcpy(ptr, str)
  1104.     register char *ptr, *str;
  1105. {
  1106.     register int len = strlen(str);
  1107.  
  1108.     while (len)
  1109.     *--ptr = str[--len];
  1110.  
  1111.     return (ptr);
  1112. } /* end strrcpy */
  1113. # endif /* hp9000s500 */
  1114. #endif /* getwd */
  1115.  
  1116. #ifdef apollo
  1117. /***
  1118.  *** Domain/OS
  1119.  ***/
  1120. #undef value            /* XXX: Careful here */
  1121. #include <apollo/base.h>
  1122. #include <apollo/loader.h>
  1123. #include <apollo/error.h>
  1124.  
  1125.  
  1126. static char *
  1127. apperr(st)
  1128.     status_$t *st;
  1129. {
  1130.     static char buf[BUFSIZE];
  1131.     short e_subl, e_modl, e_codel;
  1132.     error_$string_t e_sub, e_mod, e_code;
  1133.  
  1134.     error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
  1135.     e_sub[e_subl] = '\0';
  1136.     e_code[e_codel] = '\0';
  1137.     e_mod[e_modl] = '\0';
  1138.     (void) xsprintf(buf, "%s (%s/%s)", e_code, e_sub, e_mod);
  1139.  
  1140.     return(buf);
  1141. }
  1142.  
  1143. static int
  1144. llib(s)
  1145.     Char *s;
  1146. {
  1147.     short len = Strlen(s);
  1148.     status_$t st;
  1149.     char *t;
  1150.  
  1151.     loader_$inlib(t = short2str(s), len, &st);
  1152.     if (st.all != status_$ok) 
  1153.     stderror(ERR_SYSTEM, t, apperr(&st));
  1154. }
  1155.  
  1156. /*ARGSUSED*/
  1157. void
  1158. doinlib(v, c)
  1159.     Char **v;
  1160.     struct command *c;
  1161. {
  1162.     setname(short2str(*v++));
  1163.     gflag = 0, tglob(v);
  1164.     if (gflag) {
  1165.     v = globall(v);
  1166.     if (v == 0)
  1167.         stderror(ERR_NAME | ERR_NOMATCH);
  1168.     }
  1169.     else {
  1170.     v = gargv = saveblk(v);
  1171.     trim(v);
  1172.     }
  1173.  
  1174.     while (v && *v) 
  1175.     llib(*v++);
  1176.     if (gargv)
  1177.     blkfree(gargv), gargv = 0;
  1178. }
  1179.  
  1180. int
  1181. getv(v)
  1182.     Char *v;
  1183. {
  1184.     if (eq(v, STRbsd43))
  1185.     return(1);
  1186.     else if (eq(v, STRsys53))
  1187.     return(0);
  1188.     else 
  1189.     stderror(ERR_NAME | ERR_SYSTEM, short2str(v), "Invalid system type");
  1190.     /*NOTREACHED*/
  1191.     return(0);
  1192. }
  1193.  
  1194. /*ARGSUSED*/
  1195. void
  1196. dover(v, c)
  1197.     Char **v;
  1198.     struct command *c;
  1199. {
  1200.     Char *p;
  1201.  
  1202.     setname(short2str(*v++));
  1203.     if (!*v) {
  1204.     if (!(p = tgetenv(STRSYSTYPE)))
  1205.         stderror(ERR_NAME | ERR_STRING, "System type is not set");
  1206.     xprintf("%S\n", p);
  1207.     }
  1208.     else {
  1209.     tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
  1210.     dohash(NULL, NULL);
  1211.     }
  1212. }
  1213.  
  1214. /*
  1215.  * Many thanks to rees@citi.umich.edu (Jim Rees) and
  1216.  *                mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
  1217.  * For figuring out how to do this... I could have never done
  1218.  * it without their help.
  1219.  */
  1220. typedef short enum {
  1221.     name_$wdir_type,
  1222.     name_$ndir_type,
  1223.     name_$node_dir_type,
  1224. } name_$dir_type_t;
  1225.  
  1226. /*ARGSUSED*/
  1227. void
  1228. dorootnode(v, c)
  1229.     Char **v;
  1230.     struct command *c;
  1231. {
  1232.     name_$dir_type_t dirtype = name_$node_dir_type;
  1233.     uid_$t uid;
  1234.     status_$t st;
  1235.     char *name;
  1236.     short namelen;
  1237.  
  1238.     setname(short2str(*v++));
  1239.  
  1240.     name = short2str(*v);
  1241.     namelen = strlen(name);
  1242.  
  1243.     name_$resolve(name, &namelen, &uid, &st);
  1244.     if (st.all != status_$ok) 
  1245.     stderror(ERR_SYSTEM, name, apperr(&st));
  1246.     namelen = 0;
  1247.     name_$set_diru(&uid, "", &namelen, &dirtype, &st);
  1248.     if (st.all != status_$ok) 
  1249.     stderror(ERR_SYSTEM, name, apperr(&st));
  1250.     dohash(NULL, NULL);
  1251. }
  1252.  
  1253. int
  1254. isapad()
  1255. {
  1256.     static int res = -1;
  1257.     static status_$t st;
  1258.  
  1259.     if (res == -1) {
  1260.     int strm;
  1261.     if (isatty(0))
  1262.         strm = 0;
  1263.     if (isatty(1))
  1264.         strm = 1;
  1265.     if (isatty(2))
  1266.         strm = 2;
  1267.     else {
  1268.         res = 0;
  1269.         st.all = status_$ok;
  1270.         return(res);
  1271.     }
  1272.     res = stream_$isavt(&strm, &st);
  1273.     res = res ? 1 : 0;
  1274.     }
  1275.     else {
  1276.     if (st.all != status_$ok) 
  1277.         stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));
  1278.     }
  1279.     return(res);
  1280. }
  1281. #endif
  1282.